import { Column, Stock } from '@ant-design/charts';
import { useMutation } from '@tanstack/react-query';
import { Button, Card, Checkbox, Col, Flex, Row, Space, Table, Tag } from 'antd';
import { filter, find, head, includes, isEmpty, isEqual, isNumber, join, keys, map } from 'lodash';
import { memo, useEffect, useMemo, useState } from 'react';
import { getData } from './api';
import { easy_money_style } from './style';

type DataType = {
  value: 'f2'|'f3'|'f4'|'f5'|'f6'|'f7'|'f8'|'f9'|'f10'|'f12'|'f14'|'f15'|'f16'|'f17'|'f18'|'f22';
  label: string;
  unit?: string;
};

type StockType = {[k in DataType['value']]: string|number};

const dataColumns: DataType[] = [
  { label: '股票代码', value: 'f12' },
  { label: '股票名称', value: 'f14' },
  { label: '最新价', value: 'f2', unit: '￥' },
  { label: '涨跌幅', value: 'f3', unit: '%' },
  { label: '涨跌额', value: 'f4', unit: '￥' },
  { label: '成交量（手）', value: 'f5' },
  { label: '成交额', value: 'f6', unit: '￥' },
  { label: '振幅', value: 'f7', unit: '%' },
  { label: '换手率', value: 'f8', unit: '%' },
  { label: '市盈率', value: 'f9', unit: '%' },
  { label: '量比', value: 'f10' },
  { label: '最高', value: 'f15', unit: '￥' },
  { label: '最低', value: 'f16', unit: '￥' },
  { label: '今开', value: 'f17', unit: '￥' },
  { label: '昨收', value: 'f18', unit: '￥' },
  { label: '市净率', value: 'f22', unit: '%' },
];

const keyFn = (k: string) => (find(dataColumns, ['value', k])?.label ?? '-') + find(dataColumns, ['value', k])?.unit ?? '';

const options = map(dataColumns, i => ({ value: i.value, label: i.label }));

const columns = map(
  dataColumns,
  i => ({
    key: i.value,
    dataIndex: i.value,
    title: `${i.label}${i.unit ? `（${i.unit}）` : ''}`,
    fixed: includes(['f12', 'f14'], i.value),
    width: 200,
    render: (text: string|number) => {
      if (i.unit === '%') {
        return (<Tag className='td-tag' color={Number(text)>0 ? 'success' : 'error'} bordered={false}>{text}</Tag>);
      }
      if (isNumber(text)) {
        return text.toLocaleString()
      }
      return text || '-';
    }
  })
);

const EastMoney = () => {
  const [checked, setChecked] = useState(map(options, 'value'));
  const [pageNum, setPageNum] = useState(1);
  const [pageSize, setPageSize] = useState(20);
  const [boxData, setBoxData] = useState<StockType>();

  const { data, isPending, mutate } = useMutation({
    mutationFn: ({pn, pz}: { pn: number, pz: number }) => getData({
      fields: join(checked),
      pn,
      pz
    }),
    onSuccess(data, variables) {
      if (!isEmpty(data?.result?.data?.diff)) {
        setPageNum(variables.pn);
        setPageSize(variables.pz);
        setBoxData(head(data?.result?.data?.diff));
      }
    },
  });
  const dataSource = data?.result?.data?.diff ?? [];
  const total = data?.result?.data?.total ?? 0;
  const showColumns = keys(head(dataSource) ?? map(columns, 'key'));

  const columnConfig = useMemo(() => ({
    data: map(dataSource, i => ({...i, [keyFn('f2')]: i.f2})),
    xField: 'f14',
    yField: keyFn('f2'),
    height: 500,
    scale: { color: { palette: "tableau10" } },
    slider: {
      x: {},
    },
    state: {
      unselected: { opacity: 0.5 },
      selected: { fill: 'orange' }
    },
    interaction: {
      elementSelect: true
    }
  }), [dataSource]);

  const boxConfig = useMemo(() => {
    const data = {
      ...boxData,
      [keyFn('f17')]: boxData?.f17,
      [keyFn('f2')]: boxData?.f2,
      [keyFn('f15')]: boxData?.f15,
      [keyFn('f16')]: boxData?.f16,
    };

    return {
      data: {
        value: [data],
      },
      xField: 'f14',
      yField: [keyFn('f17'), keyFn('f2'), keyFn('f15'), keyFn('f16')],
      height: 500,
    }
  }, [boxData]);

  useEffect(() => {
    mutate({ pn: pageNum, pz: pageSize });
  }, []);

  return (
    <Row gutter={[16, 16]} className={easy_money_style}>
      <Col span={24}>
        <Space size={16}>
          <Flex vertical gap={8}>
            <Checkbox
              checked={isEqual(checked.length, options.length)}
              indeterminate={!isEmpty(checked) && !isEqual(checked.length, options.length)}
              onChange={v => setChecked(v.target.checked ? map(options, 'value') : [])}
            >全选</Checkbox>
            <Checkbox.Group options={options} value={checked} onChange={setChecked} />
          </Flex>
          <Button
            type='primary'
            loading={isPending}
            disabled={isEmpty(checked)}
            onClick={() => mutate({ pn: pageNum, pz: pageSize })}
          >查询</Button>
        </Space>
      </Col>
      <Col span={24}>
        <Card>
          <Table
            loading={isPending}
            columns={filter(columns, i => includes(showColumns, i.key))}
            dataSource={dataSource}
            scroll={{
              x: 'max-content',
              y: 600,
              scrollToFirstRowOnChange: true
            }}
            pagination={{
              total,
              current: pageNum,
              pageSize: pageSize,
              onChange: (page, size) => mutate({ pn: page, pz: size })
            }}
            onRow={
              (record: StockType) => ({
                onClick: () => setBoxData(record)
              })
            }
          />
        </Card>
      </Col>
      <Col span={12}>
        <Card>
          <Column
            {...columnConfig}
            loading={isPending}
            onReady={({ chart }) => {
              chart.on('element:click', (event: { data: { data: any; }; }) => {
                setBoxData(event?.data?.data ?? {});
              });
            }}
          />
        </Card>
      </Col>
      <Col span={12}>
        <Card>
          <Stock {...boxConfig} />
        </Card>
      </Col>
    </Row>
  );
};

export default memo(EastMoney);